package com.huige.service;

import com.huige.dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

@Transactional(timeout = 3)
@Service
public class StudentService {
    
    @Autowired
    private StudentDao studentDao;


    /**
     * 添加事务：
     *     @Transactional
     *     位置：方法/类上
     *     方法：当前方法有事务
     *     类：当前类所有方法有事务
     *
     *
     *   1.只读模式
     *      只读模式可以提升查询事务的效率！ 推荐事务中只有查询代码，使用只读模式！
     *      默认：boolean readOnly = false;
     *      解释： 一般情况下，都是通过类添加注解添加事务！
     *             类下的所有方法都有事务！
     *             查询方法可以通过再次添加注解，设置为只读模式，提高效率
     *
     *
     *    2.超时时间
     *       默认：永远不超时 -1
     *       设置 timeout = 时间 秒数 超过这个时间，就会回滚事务和释放异常！
     *       如果类上设置事务属性，方法也设置了事务注解！ 方法会不会生效？？不会
     *       不会生效：方法上的注解覆盖了类上的注解！
     *
     *
     *    3.指定异常回滚和指定异常不回滚：
     *          默认情况下，指定发生运行时异常事务才会回滚！
     *          我们可以指定Exception异常来控制所有异常都会回滚！
     *          rollbackFor = Exception.class
     *          noRollbackFor = Exception.class 回滚异常范围内，控制某个异常不回滚！
     *
     *     4.隔离级别设置
     *         推荐设置第二个隔离级别！
     *         isolation = Isolation.READ_COMMITTED
     *
     */

    @Transactional(readOnly = false ,rollbackFor = Exception.class,noRollbackFor =FileNotFoundException.class
    ,isolation = Isolation.READ_COMMITTED)
    public void changeInfo() throws FileNotFoundException {
        studentDao.updateAgeById(88,1);
        new FileInputStream("xxxx");
        System.out.println("-----------");
        studentDao.updateNameById("test2",1);
    }

    /**
     * 声明两个独立修改数据库的事务业务方法
     * propagation = Propagation.REQUIRED 父方法有事务，我们就会加入到父方法的事务！
     *               最终是同一个事务！ 推荐使用默认值
     * propagation = Propagation.REQUIRES_NEW
     *               不管父方法是否有事务，都会创建一个新的事务！
     *               父方法事务和子方法事务是两个事务！
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void changeAge(){
        studentDao.updateAgeById(998,1);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void changeName(){
        studentDao.updateNameById("xiaohong",1);
        int i = 1/0;//报错
    }

    @Transactional(readOnly = true)
    public void getStudentInfo(){
        //查询 没有必要添加事务！
        //获取学生信息 查询数据库 不修改

    }
}
